package cn.tedu.weibo.exception;
//全局异常处理器
//使用全局异常处理来对SpringMVC框架中所有Controller抛出的异常统一在这里处理
//全局异常由Spring

import cn.tedu.weibo.result.JsonResult;
import cn.tedu.weibo.result.Status;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;

//@ControllerAdvice
//使用该注解标注的类被认定为全局异常处理器
//那么一旦一个Controller中的方法抛出异常时,框架会优先找到当前类来进行处理

/*
    @RestControllerAdvice注解与@RestController道理一样
    使用它后,所有方法返回JSON格式时不用再单独添加@ResponseBody注解了

    处理异常的顺序:
    可以将当前类中处理各种异常的方法想象为原来使用try-catch中的catch.
    在这里方法在类中定义的顺序无所谓,不用像catch一样必须是子类型异常在上,超类型异常在下
    执行优先级:
    1:异常类型完全匹配最优先
    2:超类异常(可以覆盖实际抛出的异常)
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    //相当于catch(RuntimeException)
    /*@ExceptionHandler
//    @ResponseBody
    public JsonResult doHandleRuntimeException(RuntimeException e){
        System.out.println("出现了RuntimeException");
        return new JsonResult(Status.UNKNOWN_ERROR);
    }*/
    //相当于catch(IllegalArgumentException)
    @ExceptionHandler
//    @ResponseBody
    public JsonResult doHandleIllegalArgumentException(IllegalArgumentException e){
        System.out.println("出现了参数不合法异常");
        return new JsonResult(Status.OPERATION_FAILED,e.getMessage());
    }
    @ExceptionHandler
    public JsonResult doHandleMethodArgumentNotValidException(MethodArgumentNotValidException e){
        //Controller方法在验证用户提交数据时不通过会抛出上述异常
        /*
            本身的e.getMessage()在验证不通过时会抛出的异常中内容繁多
            我们可以仅将原因回复,此时使用下面的操作
         */
        String message = e.getFieldError().getDefaultMessage();
        log.warn(message,e);
        return new JsonResult(Status.VALIDATE_FAILED,message);
    }

    /**
     * 通常捕获最大类型的异常(Exception或Throwable)是用来避免
     * 因系统出现异常无法处理的情况导致响应500错误
     * @param e
     * @return
     */
    @ExceptionHandler
    public JsonResult doHandlerException(Exception e){
        log.error(e.getMessage(),e);
        return new JsonResult(Status.UNKNOWN_ERROR,e.getMessage());
    }


    @ExceptionHandler
    public JsonResult doHandleConstraintViolationException(ConstraintViolationException e){
        String message = e.getMessage();//findById.id:微博ID只能在1-9999之间
        message = message.substring(message.indexOf(":")+1).trim();
        log.warn(message,e);
        return new JsonResult(Status.VALIDATE_FAILED,message);
    }
}
